// 16位加减法器

module ADDSUB_16 (
    input clk,
    input RST,
    input [15:0] a,
    input [15:0] b,
    input c_in,
    output wire [15:0] s
);
    // wire G_out,P_out;
    wire c_out;
    
CLA_16 u_CLA_16(
    .a     (a     ),
    .b     (b     ),
    .c_in  (c_in  ),
    // .G_out (G_out ),
    // .P_out (P_out ),
    .s     (s     ),
    .c_out (c_out )
);


endmodule

// 16位超前进位加法器
module CLA_16 (
    input [15:0] a,
    input [15:0] b,
    input c_in,
    // output wire G_out,
    // output wire P_out,
    output wire [15:0] s,
    output wire c_out
);
    wire [2:0] c;
    // assign c_out = c[3];
    wire [3:0] G,P;

    // assign G_out = G[3] | P[3] & G[2] | P[3] & P[2] & G[1] | P[3] & P[2] & P[1] & G[0];
    // assign P_out = P[3] & P[2] & P[1] & P[0];

    assign c[0]  = G[0] | P[0] & c_in;
    assign c[1]  = G[1] | P[1] & G[0] | P[1] & P[0] & c_in;
    assign c[2]  = G[2] | P[2] & G[1] | P[2] & P[1] & P[0] & c_in;
    assign c_out = G[3] | P[3] & G[2] | P[3] & P[2] & G[1] | P[3] & P[2] & P[1] & G[0] | P[3] & P[2] & P[1] & P[0] & c_in;

    wire [3:0] PH;

    CLA_4 u0_CLA_4(
    	.a     (a[3:0]     ),
        .b     (b[3:0]     ),
        .c_in  (c_in  ),
        .G_out (G[0] ),
        .P_out (P[0] ),
        .s     (s[3:0]     ),
        .c_out (PH[0] )
    );
    CLA_4 u1_CLA_4(
    	.a     (a[7:4]     ),
        .b     (b[7:4]     ),
        .c_in  (c[0]  ),
        .G_out (G[1] ),
        .P_out (P[1] ),
        .s     (s[7:4]     ),
        .c_out (PH[1] )
    );
    CLA_4 u2_CLA_4(
    	.a     (a[11:8]    ),
        .b     (b[11:8]     ),
        .c_in  (c[1]  ),
        .G_out (G[2] ),
        .P_out (P[2] ),
        .s     (s[11:8]     ),
        .c_out (PH[2] )
    );
    CLA_4 u3_CLA_4(
    	.a     (a[15:12]     ),
        .b     (b[15:12]     ),
        .c_in  (c[2]  ),
        .G_out (G[3] ),
        .P_out (P[3] ),
        .s     (s[15:12]     ),
        .c_out (PH[3] )
    );
endmodule

module CLA_4 (
    input [3:0] a,
    input [3:0] b,
    input c_in,
    output wire G_out,
    output wire P_out,
    output wire [3:0] s,
    output wire c_out
);
    wire [2:0] c;
    // assign c_out = c[3];
    wire [3:0] G,P;

    assign G_out = G[3] | P[3] & G[2] | P[3] & P[2] & G[1] | P[3] & P[2] & P[1] & G[0];
    assign P_out = P[3] & P[2] & P[1] & P[0];

    assign c[0]  = G[0] | P[0] & c_in;
    assign c[1]  = G[1] | P[1] & G[0] | P[1] & P[0] & c_in;
    assign c[2]  = G[2] | P[2] & G[1] | P[2] & P[1] & P[0] & c_in;
    assign c_out = G[3] | P[3] & G[2] | P[3] & P[2] & G[1] | P[3] & P[2] & P[1] & G[0] | P[3] & P[2] & P[1] & P[0] & c_in;

    add add_0(
    	.a (a[0] ),
        .b (b[0] ),
        .c (c_in ),
        .G (G[0] ),
        .P (P[0] ),
        .s (s[0] )
    );
    add add_1(
    	.a (a[1] ),
        .b (b[1] ),
        .c (c[0] ),
        .G (G[1] ),
        .P (P[1] ),
        .s (s[1] )
    );
    add add_2(
    	.a (a[2] ),
        .b (b[2] ),
        .c (c[1] ),
        .G (G[2] ),
        .P (P[2] ),
        .s (s[2] )
    );
    add add_3(
    	.a (a[3] ),
        .b (b[3] ),
        .c (c[2] ),
        .G (G[3] ),
        .P (P[3] ),
        .s (s[3] )
    );
    
    
    
endmodule

module add (
    input a,b,c,
    output wire G,P,s
);

assign s = a ^ b ^ c;
assign G = a & b;
assign P = a | b;
    
endmodule